home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Programmer Power Tools
/
Programmer Power Tools.iso
/
rbbs_pc
/
173_asm.arc
/
BDRIVEC2.ASM
< prev
next >
Wrap
Assembly Source File
|
1983-08-04
|
24KB
|
904 lines
TITLE DRIVEIO
;
; --- CORVUS/IBM DRIVE INTERFACE UNIT FOR MICROSOFT ---
; PASCAL AND BASIC COMPILERS
; CONST ][ VERSION FOR DOS 1.10 & 2.0
;
; VERSION 1.41 BY BRK
; (MICROSOFT ASSEMBLER VERSION )
;
;
; NOTE: THIS INTERFACE UNIT NOW SUPPORTS BOTH PASCAL AND BASIC
; COMPILERS BUT IT MUST BE RE-ASSEMBLED WITH THE APPROPRIATE
; SETTING OF THE "LTYPE" EQUATE TO DO THIS FOR EACH LANGUAGE.
;
;
;
; THIS UNIT IMPLEMENTS 9 PROCEDURES:
;
; INITIO
; BIOPTR - CONST. ][
; SETSRVR - CONST. ][
; FINDSRVR - CONST. ][
; NETCMD - CONST. ][
; CDRECV = DRVRECV
; CDSEND = DRVSEND
;
; THE CALLING PROCEDURE IN PASCAL IS :
;
; CDSEND (VAR st : longstring )
;
; THE FIRST TWO BYTES OF THE STRING ARE THE LENGTH
; OF THE STRING TO BE SENT OR THE LENGTH OF THE
; STRING RECEIVED.
;
; function INITIO : INTEGER
;
; THE FUNCTION RETURNS A VALUE TO INDICATE THE STATUS OF
; THE INITIALIZATION OPERATION. A VALUE OF ZERO INDICATES
; THAT THE INITIALIZATION WAS SUCCESSFUL. A NON-ZERO VALUE
; INDICATES THE I/O WAS NOT SETUP AND THE CALLING PROGRAM
; SHOULD NOT ATTEMPT TO USE THE CORVUS DRIVERS.
;
; function BIOPTR : INTEGER
;
; THE FUNCTION RETURNS A 16 BIT POINTER TO THE "CORTAB"
; BIOS TABLE IN THE CORVUS "BIOS" DRIVERS. THIS ROUTINE
; SHOULD NOT BE EXECUTED BEFORE A SUCCESSFUL USE OF THE
; "INITIO" ROUTINE (ABOVE). NOTE: THE RETURNED VALUE IS
; RELATIVE TO "SEGMENT" ZERO, AND A RETURNED VALUE OF ZERO
; INDICATES THAT THE "CORTAB" TABLE COULD NOT BE FOUND.
;
; function SETSRVR ( srvr : integer): INTEGER
;
; THE FUNCTION RETURNS THE "BOOT SERVER" NETWORK ADDRESS.
; IF THE INPUT PARAMETER IS LESS THAN 255 ( BUT NOT NEGATIVE ),
; IT WILL BE TAKEN AS A RESET OF THE DEFAULT SERVER # WHEN
; USING THE SEND & RECIEVE ROUTINES. IF IT IS GREATER THAN 255
; OR NEGATIVE, NO CHANGE OF THE DEFAULT SERVER # WILL BE MADE.
; NOTE: THE DEFAULT SERVER # IS AUTOMATICALLY SET TO THE
; BOOT SERVER # WHEN THE "INITIO" FUNCTION IS EXECUTED.
;
; function FINDSRVR : INTEGER
;
; THE FUNCTION RETURNS THE NETWORK ADDRESS OF A VALID DISK SERVER.
; IF THE RETURNED VALUE IS GREATER THAN 63 OR NEGATIVE, THE COMMAND
; FAILED TO FIND A SERVER ( THE FLAT CABLE CARDS WOULD DO THIS ).
;
; function CARDID : INTEGER
;
; THE FUNCTION RETURNS THE CORVUS INTERFACE CARD TYPE ( 0 - OMNINET,
; 1 - FLAT CABLE ).
;
; function NETCMD ( VAR inp, VAR out: longstring) : INTEGER
;
; THE FUNCTION IS USED TO SEND/RECIEVE DATA TO A NETWORK SERVER.
; STRING inp SPECIFIES THE COMMAND TO SEND TO THE SERVER,
; AND STRING out IS WHERE ANY RETURNED DATA WILL BE PLACED
; ( THE STRING LENGTH OF out WILL NOT BE CHANGED BY THIS
; OPERATION UNLESS THE COMMAND FAILED- IN WHICH CASE THE LENGTH
; WILL BE SET TO ZERO). THE VALUE OF THE FUNCTION WILL BE
; RETURNED AS ZERO IF THE OPERATION WAS SUCCESSFUL, AND
; NON-ZERO IF IT FAILED.
; NOTE: THE SERVER # USED WILL BE THE "BOOT SERVER" # UNLESS
; THE DEFAULT IS CHANGED BY THE "SETSRVR" CMD.
;
;
;
;
; THE CALLING PROCEDURE BASIC IS :
;
; CALL CDSEND (B$ )
;
; THE FIRST TWO BYTES OF THE STRING ARE THE LENGTH
; OF THE STRING TO BE SENT OR THE LENGTH OF THE
; STRING RECEIVED ( I.E. LEFT$(B$,2) ).
;
; CALL INITIO (A%)
;
; THE FUNCTION RETURNS A VALUE TO INDICATE THE STATUS OF
; THE INITIALIZATION OPERATION. A VALUE OF ZERO INDICATES
; THAT THE INITIALIZATION WAS SUCCESSFUL. A NON-ZERO VALUE
; INDICATES THE I/O WAS NOT SETUP AND THE CALLING PROGRAM
; SHOULD NOT ATTEMPT TO USE THE CORVUS DRIVERS.
;
; CALL BIOPTR (A%)
;
; THE FUNCTION RETURNS A 16 BIT POINTER TO THE "CORTAB"
; BIOS TABLE IN THE CORVUS "BIOS" DRIVERS. THIS ROUTINE
; SHOULD NOT BE EXECUTED BEFORE A SUCCESSFUL USE OF THE
; "INITIO" ROUTINE (ABOVE). NOTE: THE RETURNED VALUE IS
; RELATIVE TO "SEGMENT" ZERO, AND A RETURNED VALUE OF ZERO
; INDICATES THAT THE "CORTAB" TABLE COULD NOT BE FOUND.
;
; CALL SETSRVR (A%) here A% is used for input and output
;
; THE FUNCTION RETURNS THE "BOOT SERVER" NETWORK ADDRESS.
; IF THE INPUT PARAMETER IS LESS THAN 255 ( BUT NOT NEGATIVE ),
; IT WILL BE TAKEN AS A RESET OF THE DEFAULT SERVER # WHEN
; USING THE SEND & RECIEVE ROUTINES. IF IT IS GREATER THAN 255
; OR NEGATIVE, NO CHANGE OF THE DEFAULT SERVER # WILL BE MADE.
; NOTE: THE DEFAULT SERVER # IS AUTOMATICALLY SET TO THE
; BOOT SERVER # WHEN THE "INITIO" FUNCTION IS EXECUTED.
;
; CALL FINDSRVR (A%)
;
; THE FUNCTION RETURNS THE NETWORK ADDRESS OF A VALID DISK SERVER.
; IF THE RETURNED VALUE IS GREATER THAN 63 OR NEGATIVE, THE COMMAND
; FAILED TO FIND A SERVER ( THE FLAT CABLE CARDS WOULD DO THIS ).
;
; CALL CARDID (A%)
;
; THE FUNCTION RETURNS THE CORVUS INTERFACE CARD TYPE ( 0 - OMNINET,
; 1 - FLAT CABLE ).
;
; CALL NETCMD ( A$,B$,C%)
;
; THE FUNCTION IS USED TO SEND/RECIEVE DATA TO A NETWORK SERVER.
; STRING A$ SPECIFIES THE COMMAND TO SEND TO THE SERVER,
; AND STRING B$ IS WHERE ANY RETURNED DATA WILL BE PLACED
; ( THE STRING LENGTH OF out WILL NOT BE CHANGED BY THIS
; OPERATION UNLESS THE COMMAND FAILED- IN WHICH CASE THE LENGTH
; WILL BE SET TO ZERO). THE VALUE OF THE FUNCTION WILL BE
; RETURNED ( IN C% ) AS ZERO IF THE OPERATION WAS SUCCESSFUL, AND
; NON-ZERO IF IT FAILED.
; NOTE: THE SERVER # USED WILL BE THE "BOOT SERVER" # UNLESS
; THE DEFAULT IS CHANGED BY THE "SETSRVR" CMD.
;
;=============================================================
; REVISION HISTORY
;
; FIRST VERSION : 10-05-82 BY BRK
; : 11-01-82 improved turn around delay for mirror
; : 02-16-83 CONST. ][ version
; : 05-16-83 added support for Basic
; : 07-06-83 fixed bug in FINDSRVR routine
; V1.40 : 07-29-83 updated for DOS 2.0
; V1.41 : 08-04-83 set timeout to zero to avoid ROM bug
;
;=============================================================
;
TRUE EQU 0FFFFH
FALSE EQU 0
;
PASCAL EQU 1 ; LANGUAGE TYPE DESCRIPTOR
BASIC EQU 2 ; LANGUAGE TYPE DESCRIPTOR
;
LTYPE EQU PASCAL ; SET TO LANGUAGE TYPE TO BE USED WITH
INTDVR EQU FALSE ; SET TO FALSE TO DISABLE INTERNAL FLAT CABLE DRIVER
;
;
; ----- CORVUS EQUATES -----
;
DATA EQU 2EEH ; DISC I/O PORT #
STAT EQU 2EFH ; DISC STATUS PORT
DRDY EQU 1 ; MASK FOR DRIVE READY BIT
DIFAC EQU 2 ; MASK FOR BUS DIRECTION BIT
ROMSEG EQU 0DF00H ; LOCATION OF CORVUS ROM
BIOSSEG EQU 60H ; STD IBM BIOS SEGMENT ADDRESS
ABTCTR EQU 0A00H ; VALUE TO SET TIMEOUT AND # OF RETRYS
; ; v1.41 timeouts=0
;
FCALL EQU 9AH ; OPCODE FOR FAR CALL
FJMP EQU 0EAH ; OPCODE FOR FAR JUMP
;
; --- MSDOS EQUATES ( V2.0 ) ---
;
VERCMD EQU 30H ; BDOS COMMAND TO GET VERSION #
HOPEN EQU 3DH ; BDOS COMMAND TO "OPEN" A FILE HANDLE
HCLOSE EQU 3EH ; BDOS COMMAND TO "CLOSE" A FILE HANDLE
HREAD EQU 3FH ; BDOS COMMAND TO "READ" FROM A FILE
HWRITE EQU 40H ; BDOS COMMAND TO "WRITE" TO A FILE
;
PGSEG SEGMENT 'CODE'
ASSUME CS:PGSEG
;
;
IF LTYPE EQ PASCAL
DB 'CORVUS/IBM PC CONST. ][ PASCAL DRIVER AS OF 08-04-83'
ENDIF
;
IF LTYPE EQ BASIC
DB 'CORVUS/IBM PC CONST. ][ BASIC DRIVER AS OF 08-04-83'
ENDIF
;
; --- COPY OF "ROM" FAR JUMP TABLE ---
;
ROMTAB PROC NEAR
DB FJMP
DW 0,ROMSEG ; FAR JUMP TO COLD BOOT ROM ENTRY
DB FJMP
DW 3,ROMSEG ; FAR JUMP TO WARM START ROM ENTRY
DB FJMP
DW 6,ROMSEG ; FAR JUMP TO I/O ROM ENTRY
DB FJMP
DW 9,ROMSEG ; FAR JUMP TO DUMMY "IRET" ENTRY
LENTAB EQU offset $-offset ROMTAB ; LENGTH OF TABLE
ROMTAB ENDP
;
; --- COPY OF CORVUS TABLE IDENTIER ---
;
CORTAB DB 'CORTAb' ; VERSION FOR CONST. ][
;
; --- COPY OF UTILITY "HOOK" DRIVER NAME ---
;
UTILPTR DB 'UTILHOOK',0
;
;
; --- THESE DATA POINTERS MUST BE KEPT IN THE SAME RELATIVE ORDER
;
SNDPTR DW 0 ; BUFFER TO SAVE POINTER TO 'SEND' STRING
SNDSEG DW 0 ; BUFFER TO SAVE 'SEND' STRING SEGMENT #
;
CORVEC DW 0,0 ; BUF TO SAVE DOUBLE WORD POINTER TO "CORTAB"
;
; --- MISC DATA AND BUFFERS ----
;
CORPTR DW 0 ; BUFFER FOR "CORTAB" POINTER
; ; INITIALIZE INITIALLY TO ZERO
CRDTYPE DB 1 ; BUFFER TO SAVE "CARD TYPE" BYTE
BOOTSRVR DB 0FFH ; BUFFER FOR "BOOT SERVER"
SRVR DB 0FFH ; BUFFER FOR "DEFAULT SERVER"
;
;
; === INITIALIZE CORVUS I/O DRIVERS ===
;
; THIS ROUTINE MUST BE CALLED
; ONCE TO SETUP THE DRIVERS BEFORE
; THEY ARE USED. IF THE ROUTINE DOES
; ANYTHING THAT CAN ONLY BE DONE ONCE,
; IT MUST DISABLE THIS SECTION SO THAT
; AND ACCIDENTAL SECOND CALL WILL NOT
; LOCK UP THE HARDWARE.
;
PUBLIC INITIO
;
INITIO PROC FAR
PUSH DS
PUSH ES
PUSH CS
POP ES ; SET ES=CS
CLD
;
MOV AH,VERCMD ; MSDOS VERSION CHECK COMMAND
INT 21H ; GET VERSION # OF DOS
OR AL,AL ; IS IT V 1.1 OR 1.0?
JZ IV11 ; YES, SO TRY FINDING "CORTAb"
;
PUSH CS
POP DS ; SET TO LOCAL SEGMENT FOR TESTING
;
MOV AH,HOPEN ; SET MSDOS 2.X, OPEN HANDLE COMMAND
MOV AL,2 ; OPEN FOR R/W
MOV DX,offset UTILPTR ; POINT TO "HOOK" DRIVER NAME
INT 21H ; DO IT
JC IV12 ; IF ERROR, TRY FOR IBM ROM
;
MOV BX,AX ; GET "HANDLE" IN (BX)
MOV AH,HWRITE ; GET WRITE CMD
MOV CX,2 ; SET TO WRITE 2 CHARS
MOV DX,offset UTILPTR ; USE NAME FOR SOURCE OF CHARACTERS
INT 21H ; THIS SHOULD RESET "POINTER" IN DRIVER
;
MOV AH,HREAD ; SET READ CMD
MOV CX,4 ; SET TO READ DOUBLE WORD
MOV DX,offset CORVEC ; POINT TO DESTINATION OF READ
INT 21H ; DO IT
;
MOV AH,HCLOSE ; GET CLOSE CMD
INT 21H ; CLOSE HANDLE
;
LDS BX,dword ptr CORVEC ; GET POSSIBLE POINTER TO "CORTAb"
CALL BIOT1 ; TEST FOR "CORTAb"
JNC OKEXIT ; IF OK, EXIT
JMP IV12 ; OTHERWISE PROCEED
;
IV11: MOV AX,BIOSSEG ; SET TO TEST STD IBM SEGMENT ADD
CALL BIOTST ; TEST BIOS AND LINK TO IT IF OK
JNC OKEXIT ; IF OK, EXIT
MOV AX,BIOSSEG-20H ; TRY MICROSOFT STD LOCATION (40H)
CALL BIOTST
JNC OKEXIT ; IF OK, EXIT
;
IV12: MOV AX,ROMSEG
MOV DS,AX ; SET DS=ROM SEGMENT
XOR AX,AX ; GET A ZERO
MOV BX,AX ; POINT TO START OF ROM
MOV DI,AX ; INIT CHECKSUM COUNTER
MOV CX,4 ; CHECK FOR 4 JUMPS AT START OF ROM
;
CKROM: MOV AL,[BX] ; READ POSSIBLE OPCODE BYTE
ADD DI,AX ; SUM THE TEST BYTES
ADD BX,3 ; POINT TO POSSIBLE NEXT OPCODE
LOOP CKROM ; SUM THE OPCODES
;
CMP DI,4*(0E9H) ; SHOULD BE 4 0E9H OPCODES (JMP)
;
IF INTDVR
JNZ OKEXIT ; NO, SO LEAVE DEFAULT DRIVERS
ENDIF
;
IF NOT INTDVR
JNZ BDEXIT ; NO, SO LEAVE WITH ERROR CONDITION
ENDIF
;
PUSH CS
POP DS ; DS=ES=CS
;
MOV SI,offset ROMTAB ; POINT TO SOURCE (ROM CALL TABLE COPY)
CALL CPYTAB ; COPY TABLES
;
DB FCALL
DW 3,ROMSEG ; FAR CALL TO ROM "INIT" ROUTINE
;
MOV AH,0 ; COMMAND FOR CARD TYPE IDENTIFY
;
DB FCALL
DW 6,ROMSEG ; FAR CALL TO DRIVE I/O ROM ENTRY
;
MOV CS:CRDTYPE,AL ; SAVE CARD TYPE []
;
OR AL,AL ; TEST FOR OMNINET
JNZ OKEXIT ; IF FLAT, EXIT
MOV AH,4 ; SET TO FIND SERVER ADDRESS
MOV BX,ABTCTR ; SET ABORT TIME AND RETRYS
;
DB FCALL
DW 6,ROMSEG ; FAR CALL TO DRIVE I/O ROM ENTRY
;
MOV CS:BOOTSRVR,AH ; SAVE SERVER #
MOV CS:SRVR,AH
OR AL,AL ; WAS SERVER # ACTUALLY FOUND
BDEXIT: MOV AX,1 ; SET FOR ERROR CONDITION
JNZ INEXIT ; NO, SO SHOW ERROR AND EXIT
;
OKEXIT: MOV AX,0 ; RETURN A ZERO
INEXIT: POP ES
POP DS
;
IF LTYPE EQ PASCAL
RET
ENDIF
;
IF LTYPE EQ BASIC
PUSH BP
MOV BP,SP
MOV BX,6 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN ERROR CONDITION BYTE
POP BP
RET 2
ENDIF
;
INITIO ENDP
;
; --- COPY ADDRESS INFORMATION FROM SOURCE POINTED TO BY DS:SI ---
;
CPYTAB PROC NEAR
MOV DI,offset LNKTAB ; POINT TO ROUTINE LINKAGE TABLE
MOV CX,LENTAB ; SET TO COPY
REP MOVSB ; DO COPY
RET
CPYTAB ENDP
;
; --- TEST FOR "CORVUS" CONST ][ BIOS ---
;
BIOTST PROC NEAR
MOV DS,AX ; SET DATA SEGMENT TO THAT OF "BIOS"
MOV BX,1 ; POINT TO "INIT" ADDRESS FIELD OF JUMP
MOV BX,[BX] ; GET THIS ADDRESS IN BX
ADD BX,1 ; OFFSET FOR INSTRUCTION SIZE
MOV BX,[BX] ; GET POSSIBLE POINTER TO "CORTAb" STRING
;
BIOT1 PROC NEAR
MOV SI,BX ; SAVE IT
MOV DI,offset CORTAB ; POINT TO LOCAL COPY OF STRING
MOV CX,6 ; LENGTH OF STRING
REPZ CMPSB ; COMPARE STRINGS
STC ; SET CARRY TO INDICATE POSSIBLE MISMATCH
JNZ BIOE ; EXIT IF MISMATCH
;
MOV AX,DS ; GET "BIOS" SEGMENT
MOV CL,4 ; SET TO MULTIPLY BY 16
SHL AX,CL ; CONVERT SEGMENT # TO ADDRESS
ADD AX,BX ; FIND "CORTAb" ADDRESS RELATIVE TO SEG. 0
MOV CS:CORPTR,AX ; SAVE FOR POSSIBLE USE []
;
MOV AL,35 [BX] ; GET "BOOT SERVER" # FROM BIOS
MOV CS:BOOTSRVR,AL ; SAVE IT []
MOV CS:SRVR,AL ; INIT "DEFAULT SERVER" AS "BOOT SERVER" []
;
ADD BX,23 ; OFFSET TO ROM FUNCTION TABLE POINTER
MOV SI,[BX] ; GET IT
CALL CPYTAB ; COPY TABLE INTO THIS DRIVER
MOV AH,0 ; ID COMMAND
CALL far ptr CRVIO ; DO IT
MOV CS:CRDTYPE,AL ; SAVE CARD TYPE
CLC ; CLEAR CARRY TO INDICATE SUCCESS
BIOE: RET
;
BIOT1 ENDP
BIOTST ENDP
;
;
; === RETURN POINTER TO "CORTAb" IN CORVUS BIOS ===
;
PUBLIC BIOPTR
;
BIOPTR PROC FAR
MOV AX,CS:CORPTR ; GET POINTER []
;
IF LTYPE EQ PASCAL
RET
ENDIF
;
IF LTYPE EQ BASIC
PUSH BP
MOV BP,SP
MOV BX,6 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN POINTER
POP BP
RET 2
ENDIF
;
BIOPTR ENDP
;
; ==== SET SERVER # AND READ BOOT SERVER # ====
;
PUBLIC SETSRVR
;
SETSRVR PROC FAR
PUSH BP ; SAVE FRAME POINTER
MOV BP,SP ; SET NEW ONE
;
IF LTYPE EQ PASCAL
MOV CX,6 [BP] ; GET PASSED VALUE
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,6 [BP] ; GET POINTER TO VALUE
MOV CX,[BX] ; GET ITS VALUE
ENDIF
;
OR CH,CH ; IS IT TOO BIG?
JNZ SETS1 ; YES, SO DO NOT CHANGE PRESENT VALUE
MOV CS:SRVR,CL ; NO, SO SET NEW DEFAULT SERVER #
SETS1: XOR AX,AX ; GET A ZERO
MOV AL,CS:BOOTSRVR ; GET "BOOT SERVER" # AS RETURN VALUE
;
IF LTYPE EQ BASIC
MOV [BX],AX ; SET RETURNED VALUE
ENDIF
;
POP BP ; RESTORE FRAME
RET 2
SETSRVR ENDP
;
; === FIND A VALID NETWORK SERVER ADDRESS ===
;
PUBLIC FINDSRVR
;
FINDSRVR PROC FAR
MOV AH,4 ; FIND SERVER COMMAND ( 1.31 bug fix )
MOV BX,ABTCTR ; SET MAX RETRY COUNT AND ABORT TIME
CALL far ptr CRVIO ; CALL I/O DRIVER
XCHG AL,AH ; GET SERVER # IN LSB
;
IF LTYPE EQ PASCAL
RET
ENDIF
;
IF LTYPE EQ BASIC
PUSH BP
MOV BP,SP
MOV BX,6 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN SERVER #
POP BP
RET 2
ENDIF
;
FINDSRVR ENDP
;
; === IDENTIFY CORVUS I/O CARD TYPE ===
;
PUBLIC CARDID
;
CARDID PROC FAR
MOV AH,0 ; ZERO MSB
MOV AL,CS:CRDTYPE ; GET CARD IDENTIFIER
;
IF LTYPE EQ PASCAL
RET
ENDIF
;
IF LTYPE EQ BASIC
PUSH BP
MOV BP,SP
MOV BX,6 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN CARD TYPE
POP BP
RET 2
ENDIF
;
CARDID ENDP
;
; === SEND/RECEIVE A COMMAND TO A NETWORK SERVER ===
;
PUBLIC NETCMD
;
NETCMD PROC FAR
PUSH BP ; SAVE FRAME POINTER
MOV BP,SP ; SET NEW ONE
;
IF LTYPE EQ PASCAL
MOV SI,6 [BP] ; GET ADDRESS OF INPUT STRING
MOV DI,8 [BP] ; GET ADDRESS OF OUTPUT STRING
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,6 [BP] ; GET ADDRESS OF STRING DESCRIPTOR
MOV SI,[BX] ; GET ADDRESS OF INPUT STRING
MOV BX,8 [BP] ; GET ADDRESS OF STRING DESCRIPTOR
MOV DI,[BX] ; GET ADDRESS OF OUTPUT STRING
ENDIF
;
PUSH DS
POP ES ; SET ES=DS (SAVE SEGMENT)
;
MOV CX,[SI] ; LOOK AT LENGTH
MOV AL,CL ; SAVE FOR RETURN STATUS
JCXZ NETE ; IF ZERO, SET RET LENGTH TO ZERO AND RET
;
PUSH DI
INC SI
INC SI ; POINT TO SEND DATA ( DS:SI )
;
INC DI
INC DI ; POINT TO PLACE TO SAVE RETURNED DATA ( ES:DI)
;
MOV DX,530 ; SET MAX # OF RETURNED BYTES
;
MOV AH,3 ; SET FOR SERVER CMD
MOV AL,CS:SRVR ; SET DISK SERVER #
MOV BX,ABTCTR ; SET ABORT TIME AND # OF RETRYS
CALL far ptr CRVIO ; DO DISK I/O
;
POP DI ; GET POINTER BACK TO LENGTH
MOV CX,[DI] ; GET LENGTH PREVIOUSLY SET
NETE: MOV [DI],CX ; SET LENGTH OF RETURNED STRING
MOV AH,0 ; CLEAR MSB OF RETURNED VALUE
;
IF LTYPE EQ PASCAL
POP BP ; GET FRAME POINTER BACK
RET 4 ; CLEAR RETURN STACK
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,10 [BP] ; GET POINTER TO DATA "INTEGER"
MOV [BX],AX ; RETURN ERROR CONDITION BYTE
POP BP
RET 6
ENDIF
;
NETCMD ENDP
;
; === RECEIVE A STRING OF BYTES FROM THE DRIVE ===
;
PUBLIC CDRECV, DRVRECV
;
CDRECV PROC FAR
DRVRECV:
PUSH BP ; SAVE FRAME POINTER
MOV BP,SP ; SET NEW ONE
;
IF LTYPE EQ PASCAL
MOV DI,6 [BP] ; GET ADDRESS OF STRING TO SAVE DATA IN
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,6 [BP] ; GET ADDRESS OF STRING DESCRIPTOR
INC BX
INC BX ; POINT TO STRING POINTER
MOV DI,[BX] ; GET ADDRESS OF STRING TO SAVE DATA IN
ENDIF
;
PUSH DS
POP ES ; SET ES=DS (SAVE SEGMENT)
;
PUSH DI
PUSH DS
;
LDS SI,CS:dword ptr SNDPTR ; GET POINTER TO SOURCE STRING
MOV CX,[SI] ; LOOK AT LENGTH
MOV AL,CL ; SAVE FOR RETURN STATUS
JCXZ RLPE ; IF ZERO, SET RET LENGTH TO ZERO AND RET
;
INC SI
INC SI ; POINT TO SEND DATA ( DS:SI )
;
INC DI
INC DI
INC DI ; POINT TO PLACE TO SAVE RETURNED DATA ( ES:DI)
;
MOV DX,530 ; SET MAX # OF RETURNED BYTES
;
MOV AH,1 ; SET FOR "BCI" LIKE COMMAND
MOV AL,CS:SRVR ; SET DISK SERVER #
MOV BX,ABTCTR ; SET ABORT TIME AND # OF RETRYS
CALL far ptr CRVIO ; DO DISK I/O
;
RLPE: POP DS
POP DI ; GET POINTER BACK TO LENGTH
MOV [DI],CX ; SET LENGTH OF RETURNED STRING
MOV 2 [DI],AL ; SAVE RETURN STATUS
POP BP ; GET FRAME POINTER BACK
RET 2 ; CLEAR RETURN STACK
CDRECV ENDP
;
; === SEND STRING OF BYTES TO DRIVE ===
;
; THIS CONSTELLATION VERSION
; JUST SAVES TWO POINTERS TO
; THE DATA STRING TO SEND. THE
; CDRECV ROUTINE ACTUALLY SENDS
; THE DATA AND RECEIVES THE
; RETURN STATUS
;
PUBLIC CDSEND, DRVSEND
;
CDSEND PROC FAR
DRVSEND:
PUSH BP ; SAVE FRAME POINTER
MOV BP,SP ; SET NEW ONE
;
IF LTYPE EQ PASCAL
MOV AX,6 [BP] ; GET ADDRESS OF STRING TO SEND
ENDIF
;
IF LTYPE EQ BASIC
MOV BX,6 [BP] ; GET ADDRESS OF STRING DESCRIPTOR
INC BX
INC BX ; POINT TO STRING POINTER
MOV AX,[BX] ; GET ADDRESS OF STRING TO SAVE DATA IN
ENDIF
;
MOV CS:SNDPTR,AX ; SAVE IT []
;
MOV AX,DS ; GET DATA SEGMENT
MOV CS:SNDSEG,AX ; SAVE IT []
;
POP BP ; GET FRAME POINTER BACK
RET 2 ; CLEAR RETURN STACK
CDSEND ENDP
;
;
;
;
; ============ FLAT CABLE R/W ROUTINES ==============
;
; THESE ROUTINES ARE ESSENTIALLY THE SAME AS THE FLAT CABLE
; DRIVERS IN THE "ROM". THEY ARE REPRODUCED HERE SO THAT
; SYSTEMS WITH FLAT CABLE INTERFACES NEED NOT HAVE A "ROM"
; TO WORK WITH CONSTELLATION ][ SOFTWARE.
;
; --- BUFFERS USED BY "ROM" DRIVER ROUTINES ---
;
CLICKS DB 0 ; BUFFER FOR SAVING # OF CLOCK TICKS
STOPTM DW 0 ; BUFFER FOR SAVING STOP TIME
RMCMD DB 0 ; BUFFER FOR SAVING PASSED "ROM" CMD
BLKLEN DW 512 ; BUFFER FOR SAVING # OF BYTES TO XFER
CMDLEN DW 4 ; BUFFER FOR SAVING LENGTH OF CMD
RTNCODE DB 0 ; BUFFER FOR SAVING DISK RETURN CODE
;
; --- SET TIMER ---
;
STIME PROC NEAR
XOR AH,AH ; READ TIME OF DAY CLOCK
INT 1AH
JMP STIME1
;
; --- CHECK FOR TIMOUT ---
;
CKTIME: CMP CS:CLICKS,0 ; WAS A WAIT REQUESTED? []
CLC
JZ CKRET ; NO, SO RETURN WITH CARRY CLEAR
XOR AH,AH ; TIME OF DAY CALL
INT 1AH
OR AL,AL ; HAS CLOCK WRAPPED AROUND TO ZERO?
JZ CKT1 ; NO
;
; IF CLOCK HAS PASSED 24 HOURS, RECALCULATE STOP TIME
;
STIME1: MOV AL,CS:CLICKS ; GET # OF CLOCK TICKS OF DELAY []
XOR AH,AH
MOV CL,4 ; SET TO MULTIPLY BY 16
SHL AX,CL ; DO IT BY SHIFTING
ADD DX,AX
MOV CS:STOPTM,DX ; SAVE STOP TIME []
CHKOK: CLC ; CLEAR CARRY ( TIME CHECK IS OK )
RET
;
CKT1: CMP DX,CS:STOPTM ; TIMEOUT? []
JB CHKOK
;
STC ; SET CARRY IF TIMEOUT
CKRET: RET
STIME ENDP
;
; ---- MAIN DRIVER ENTRY POINT ---
;
DRVIO PROC FAR
CLD ; SET FOR "INCREMENT"
MOV CS:RMCMD,AH ; SAVE COMMAND []
CMP AH,1 ; IS IT A "BCI" COMMAND?
JZ RW15 ; YES, SO DO IT
CMP AH,5 ; IS IT A "WRITE" COMMAND?
JZ RW15 ; YES, SO DO IT
CMP AH,0 ; IS IT AN "IDENTIFY" COMMAND
JZ RW00 ; YES, SO DO IT
MOV AL,0FFH ; IF ANY OTHER, INDICATE "ABORT" OR ERROR
MOV CX,0
RET ; LONG RET
;
RW00: MOV AL,1 ; INDICATE FLAT CABLE
RET ; LONG RET
;
;
RW15: PUSH DS ; SAVE REGISTERS THAT MAY BE CHANGED
PUSH SI
PUSH DI
PUSH BX
PUSH DX
;
MOV CS:CLICKS,BL ; SAVE # OF TIMER CLICKS []
MOV CS:BLKLEN,DX ; SAVE BLOCK LENGTH []
MOV CS:CMDLEN,CX ; SAVE CMD LENGTH []
CALL ROMIO ; DO DISK I/O
POP DX
POP BX
POP DI
POP SI
POP DS
MOV AL,CS:RTNCODE ; GET RETURN CODE []
;
DMYLRET LABEL FAR
RET ; LONG RET
;
DMYIRET LABEL FAR
IRET ; DUMMY "IRET"
;
DRVIO ENDP
;
ROMIO PROC NEAR
CALL STIME ; SETUP TIMER COUNT
;
RO1: MOV DX,STAT ; POINT TO STATUS PORT
CLI ; DISABLE INTERRUPTS FOR TEST
IN AL,DX ; READ DRIVE STATUS BYTE
TEST AL,DRDY ; IS IT READY?
JZ RO2 ; YES, SO PROCEED
STI ; NO, SO RE-ENABLE INTERRUPTS
CALL CKTIME ; CHECK IF TIMED OUT
JNC RO1 ; IF NOT, TRY AGAIN
ARET: MOV CS:RTNCODE,0FFH ; IF TIMED OUT, SET ERROR []
MOV CX,0 ; INDICATE NO DATA RETURNED
RET
;
RO2: MOV CX,CS:CMDLEN ; GET CMD LENGTH []
CALL SNDBLK ; SEND BLOCK OF DATA TO DRIVE
CMP CS:RMCMD,5 ; WAS CMD A "WRITE" CMD? []
JNZ RCVBLK ; NO, SO GO RECEIVE DATA
;
MOV SI,DI ; YES, POINT TO SECTOR DATA
MOV AX,ES
MOV DS,AX
MOV CX,CS:BLKLEN ; GET LENGTH OF DATA BLOCK []
CALL SNDBLK ; SEND SECTOR DATA
;
RCVBLK: CALL STIME ; SET TIMER
;
CALL DELAY1 ; DELAY
;
RCV1: CALL CKTIME ; TIMED OUT YET?
JC ARET ; YES, SO RETURN WITH ERROR
;
RCV2: MOV DX,STAT ; POINT TO STATUS PORT
IN AL,DX ; READ DRIVE STATUS BYTE
TEST AL,DIFAC ; TEST BUS DIRECTION
JNZ RCV1 ; WAIT FOR "HOST TO DRIVE"
TEST AL,DRDY ; TEST IF ALSO READY
JNZ RCV1
;
CALL DELAY1 ; WAIT TO BE SURE
;
IN AL,DX ; TEST STATUS AGAIN
TEST AL,DIFAC
JNZ RCV1 ; IF FALSE ALARM, TRY AGAIN
TEST AL,DRDY
JNZ RCV1 ; IF NOT READY, TRY AGAIN
;
DEC DX ; POINT TO DATA PORT
IN AL,DX ; GET RETURN CODE
INC DX ; POINT BACK TO STATUS PORT
;
MOV CX,1 ; INDICATE 1 BYTE WAS RETURNED
MOV CS:RTNCODE,AL ; SAVE IT []
CMP CS:RMCMD,5 ; WAS CMD A "WRITE" CMD []
JZ RCRET ; YES, SO RETURN
;
MOV BX,CX ; OTHERWISE SET COUNTER
MOV CX,CS:BLKLEN ; GET LENGTH OF EXPECTED DATA
;
RCV3: IN AL,DX ; GET STATUS AGAIN
TEST AL,DRDY ; IS DRIVE READY?
JNZ RCV3 ; NO, SO WAIT
TEST AL,DIFAC ; ARE WE DONE?
JNZ RCV4 ; POSSIBLY, ...
;
DEC DX ; POINT TO DATA PORT
IN AL,DX ; GET DATA FROM DRIVE
INC DX ; POINT BACK TO STATUS PORT
;
JCXZ RCVS ; IF DATA NOT WANTED
STOSB ; SAVE DATA IN BUFFER
DEC CX ; COUNT DOWN # TO SAVE
;
RCVS: INC BX ; COUNT UP # RECEIVED
JMP RCV3 ; LOOP UNTIL EXIT
;
RCV4: IN AL,DX ; GET STATUS BYTE
TEST AL,DRDY ; IS DRIVE READY
JNZ RCV3 ; NO, SO PREVIOUS RESULT MAY BE FALSE
TEST AL,DIFAC ; IS IT STILL "HOST TO DRIVE"?
JZ RCV3 ; NO, SO TRY AGAIN
;
MOV CX,BX ; GET # OF BYTES RECEIVED
RCRET: RET
;
DELAY1: MOV BL,15 ; SET DELAY
DELAY: DEC BL
JNZ DELAY ; LOOP UNTIL DONE
RET
;
; --- SEND BLOCK OF DATA TO DRIVE ---
;
SNDBLK: MOV DX,STAT ; POINT TO STATUS PORT
;
SND1: IN AL,DX ; GET STATUS BYTE
TEST AL,DRDY ; IS DRIVE READY?
JNZ SND1 ; NO, SO LOOP
;
DEC DX ; POINT TO DATA PORT
LODSB ; GET DATA FROM MEMORY
OUT DX,AL ; SEND DATA TO DRIVE
INC DX ; POINT BACK TO STATUS PORT
;
STI ; RE-ENABLE INTERRUPTS
LOOP SND1 ; CONTINUE UNTIL DONE
RET
;
ROMIO ENDP
;
;
; ---- INTERFACE "FAR" CALL TABLE ---
; THIS TABLE GETS PATCHED
; TO EITHER "BIOS" CALLS OR
; "ROM" CALLS IF THE APPROPRIATE
; LINK IS FOUND
;
LNKTAB PROC NEAR
JMP DMYLRET ;
JMP DMYLRET ;
;
CRVIO LABEL FAR
JMP DRVIO ; THIS SHOULD BE A FAR CALL
;
JMP DMYIRET ; THIS SHOULD BE A FAR JUMP
LNKTAB ENDP
;
; =========================================================
;
PGSEG ENDS
;
;
END